package com.meelive.ingkee.iknetwork.diagnose

import android.app.*
import android.content.pm.ActivityInfo
import android.content.res.TypedArray
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.gmlive.common.ui.systembartint.SystemBarUtil
import com.meelive.ingkee.base.utils.concurrent.ThreadPools
import com.meelive.ingkee.base.utils.text.StringUtils
import com.meelive.ingkee.iknetwork.diagnose.api.IKNetworkDiagnoseContract
import com.meelive.ingkee.iknetwork.diagnose.model.IKNetworkDiagnoseBaseInfo
import com.meelive.ingkee.iknetwork.diagnose.model.IKNetworkDiagnoseConfig
import com.meelive.ingkee.iknetwork.diagnose.util.DiagnosePares
import com.meelive.ingkee.iknetwork.diagnose.util.InKeNetworkDiagnoseUtil
import com.meelive.ingkee.iknetwork.diagnose.viewmodel.IKNetworkDiagnoseViewModel
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.launch

class CheckNetworkActivity : AppCompatActivity() {

    companion object {
        const val CONTENT_FRAGMENT_NAME = "content_fragment_name"
        private const val CONTENT_FRAGMENT = "content_fragment"
        const val CONFIG_JSON = "config_json"
        const val COPY_VIEW_CONFIG = "copy_view_config"
        const val TITLE_VIEW_CONFIG = "title_view_config"
        const val BASE_INFO_JSON = "base_info_json"
    }

    private var config: IKNetworkDiagnoseConfig? = null
    private var baseInfo: IKNetworkDiagnoseBaseInfo? = null

    private val viewModel: IKNetworkDiagnoseViewModel
        get() = ViewModelProvider(this).get(IKNetworkDiagnoseViewModel::class.java)

    private val checkInfo = StringBuilder()

    private var init = false

    override fun onCreate(savedInstanceState: Bundle?) {

        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O && isTranslucentOrFloating()) {
            val result: Boolean = fixOrientation()
            Log.i("CheckNetworkActivity", "onCreate fixOrientation when Oreo, result = $result")
        }

        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_check_network)

        SystemBarUtil.setTranslucentStatus(this)
        // 状态栏颜色
        SystemBarUtil.setStatusBarDarkTheme(this, true)

        init = true

        intent?.apply {
            if (hasExtra(CONTENT_FRAGMENT_NAME)) {
                val fragmentName = getStringExtra(CONTENT_FRAGMENT_NAME)

                var fragment = supportFragmentManager.findFragmentByTag(CONTENT_FRAGMENT)

                if (fragment == null) {
                    fragmentName?.apply {
                        val fragmentClass = classLoader?.loadClass(this)
                        val constructor = fragmentClass?.getDeclaredConstructor()
                        fragment = constructor?.newInstance() as? Fragment

                        fragment?.apply {
                            arguments = Bundle()
                            if (hasExtra(COPY_VIEW_CONFIG)) {
                                arguments?.putString(COPY_VIEW_CONFIG, getStringExtra(COPY_VIEW_CONFIG))
                            }
                            if (hasExtra(TITLE_VIEW_CONFIG)) {
                                arguments?.putString(TITLE_VIEW_CONFIG, getStringExtra(TITLE_VIEW_CONFIG))
                            }
                            supportFragmentManager.beginTransaction().add(R.id.parent_content, this, CONTENT_FRAGMENT).commit()
                        }
                    }
                }
            }

            if (hasExtra(CONFIG_JSON)) {
                config = DiagnosePares.parseJson(getStringExtra(CONFIG_JSON), IKNetworkDiagnoseConfig::class.java)
            }

            if (hasExtra(BASE_INFO_JSON)) {
                baseInfo = DiagnosePares.parseJson(getStringExtra(BASE_INFO_JSON), IKNetworkDiagnoseBaseInfo::class.java)
            }
        }
        initWindowEnterAnim()
    }

    override fun setContentView(layoutResID: Int) {
        super.setContentView(layoutResID)
        setFitSystemWindows()
    }

    override fun setContentView(view: View?) {
        super.setContentView(view)
        setFitSystemWindows()
    }

    override fun setContentView(view: View?, params: ViewGroup.LayoutParams?) {
        super.setContentView(view, params)
        setFitSystemWindows()
    }

    override fun onResume() {
        super.onResume()
        config?.takeIf { init }?.apply {
            init = false
            viewModel.analyzeConfig(baseInfo, this) {
                when {
                    it.error -> {
                        messageShowError(it.message)
                    }
                    it.completed -> {
                        messageShowComplete(it.message)
                    }
                    else -> {
                        showMessage(it.message)
                    }
                }
            }
        }
    }

    override fun setRequestedOrientation(requestedOrientation: Int) {
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O && isTranslucentOrFloating()) {
            Log.i("CheckNetworkActivity", "avoid calling setRequestedOrientation when Oreo.")
            return
        }
        super.setRequestedOrientation(requestedOrientation)
    }

    private fun getContract(): IKNetworkDiagnoseContract? {
        if (!supportFragmentManager.isDestroyed) {
            val fragment = supportFragmentManager.findFragmentByTag(CONTENT_FRAGMENT)

            if (fragment is IKNetworkDiagnoseContract) {
                return fragment
            }
        }
        return null
    }

    private fun showMessage(message: String?) {
        if (!StringUtils.isEmpty(message)) {
            checkInfo.append(message)
            getContract()?.showMessage(checkInfo.toString())
        }
    }

    private fun messageShowComplete(result: String) {
        getContract()?.messageShowComplete(result)
        saveResult(result)
    }

    private fun messageShowError(result: String) {
        getContract()?.messageShowError(result)
        saveResult(result)
    }

    private fun saveResult(message: String) {
        GlobalScope.launch(ThreadPools.IO_THREAD_POOL.get().asCoroutineDispatcher()) {
            val result = "${checkInfo}\n${message}"
            InKeNetworkDiagnoseUtil.copyDiagnoseToFile(result)
        }
    }

    override fun finish() {
        super.finish()
        initWindowExitAnim()
    }

    /**
     * 初始化进入动画
     */
    private fun initWindowEnterAnim() {
        overridePendingTransition(R.anim.slide_right_in, R.anim.empyt_anim)
    }

    /**
     * 初始化退出动画
     */
    private fun initWindowExitAnim() {
        overridePendingTransition(R.anim.empyt_anim, R.anim.slide_right_out)
    }

    private fun setFitSystemWindows() {
        SystemBarUtil.setRootViewFitsSystemWindows(this, true)
    }

    // 解决8.0崩溃问题
    private fun isTranslucentOrFloating(): Boolean {
        var isTranslucentOrFloating = false
        try {
            val styleableRes = Class.forName("com.android.internal.R\$styleable").getField("Window")[null] as IntArray
            val ta = obtainStyledAttributes(styleableRes)
            val m = ActivityInfo::class.java.getMethod("isTranslucentOrFloating", TypedArray::class.java)
            m.isAccessible = true
            isTranslucentOrFloating = m.invoke(null, ta) as Boolean
            m.isAccessible = false
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
        return isTranslucentOrFloating
    }

    private fun fixOrientation(): Boolean {
        try {
            val field = Activity::class.java.getDeclaredField("mActivityInfo")
            field.isAccessible = true
            val o = field[this] as ActivityInfo
            o.screenOrientation = -1
            field.isAccessible = false
            return true
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }
}